import { Component, Inject, HttpException, HttpStatus } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { DeepPartial, DeleteResult, Repository } from 'typeorm';
import sha256 from 'crypto-js/sha256';
import hmacSHA512 from 'crypto-js/hmac-sha512';
import Base64 from 'crypto-js/enc-base64';
import jwt from 'jsonwebtoken';

import { UserEntity } from './user.entity';
import { CreateUserDto } from './user.dto';
import { SECRET } from '../config';
import { UserRO } from './user.interface';

import { validate } from 'class-validator';

@Component()
export class UserService {
  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepository: Repository<UserEntity>,
  ) {}

  // 查询所有的数据
  async findAll(): Promise<UserEntity[]> {
    return await this.userRepository.find();
  }

  // 查询一条数据
  async findOne(options?: DeepPartial<UserEntity>): Promise<UserEntity> {
    return await this.userRepository.findOne(options);
  }

  // 创建用户
  async creat(userData: CreateUserDto): Promise<UserRO> {
    // 用户密码加密
    const hashDigest = sha256(userData.password);
    const hmacDigest = Base64.stringify(hmacSHA512(hashDigest, SECRET));
    const user = new UserEntity();
    user.username = userData.username;
    user.email = userData.email;
    user.password = userData.password;

    const errors = await validate(user);
    if (errors.length > 0) {
      console.log(errors);
      throw new HttpException('Data not valid', HttpStatus.BAD_REQUEST);
    } else {
      // Todo: handle email unique validator better
      const savedUser = await this.userRepository.save(user);
      const userRO = {
        username: savedUser.username,
        email: savedUser.email,
        bio: savedUser.bio,
        token: this.generateJWT(savedUser),
        image: null,
      };
      return { user: userRO };
    }
  }

  // 更新用户数据
  async update(id: string, userData: any): Promise<UserEntity> {
    const toUpdate = await this.userRepository.findOneById(id);
    if (userData.id) delete userData.id;
    const updated = Object.assign(toUpdate, userData);
    return await this.userRepository.save(updated);
  }

  // 删除用户
  async delete(email: string): Promise<DeleteResult> {
    return await this.userRepository.delete({ email: email });
  }

  async findById(id: string): Promise<UserEntity> {
    const user = await this.userRepository.findOneById(id);
    if (user) delete user.password;
    return user;
  }

  // 根据邮箱查找
  async findByEmail(email: string) {
    const user = await this.userRepository.findOne({ email: email });
    if (user) delete user.password;
    return user;
  }

  // token生成
  generateJWT(user) {
    const today = new Date();
    const exp = new Date(today);
    // 60天后
    exp.setDate(today.getDate() + 60);
    // exp 过期时间
    return jwt.sign(
      {
        id: user.id,
        username: user.username,
        exp: exp.getTime() / 1000,
      },
      SECRET,
    );
  }
}
